/*
  Losu Copyright Notice
  --------------------
    Losu is an open source programming language project under the MIT license
  that can be used for both academic and commercial purposes. There are no
  fees, no royalties, and no GNU-like restrictions. Losu qualifies
  as open source software. However, Losu is not public property, and founder
  'chen-chaochen' retains its copyright.

    Losu has been registered with the National Copyright Administration of the
  People's Republic of China, and adopts the MIT license as the copyright
  licensing contract under which the right holder conditionally licenses its
  reproduction, distribution, and modification rights to an unspecified public.

    If you use Losu, please follow the public MIT agreement or choose to enter
  into a dedicated license agreement with us.

  The MIT LICENSE is as follows
  --------------------
  Copyright  2020  chen-chaochen

    Permission is hereby granted, free of charge, to any person obtaining a
  copy of this software and associated documentation files (the “Software”), to
  deal in the Software without restriction, including without limitation the
  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  sell copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  SOFTWARE.
*/

#ifndef HETU_VIEW_H
#define HETU_VIEW_H

#include "losu.h"

#if 1  // object

typedef struct hetu_backend_obj* hetu_backend_obj_t;  // vendor backend handle

typedef struct hetu_object {
  hetu_backend_obj_t backend;  // backend 结构指针
  struct hetu_style* style;    // 样式指针
  struct hetu_object* parent;  // 父对象指针
} hetu_object, *hetu_object_t;

// 基址 节点
losu_extern_t hetu_object_t HetuObj_Base;

// in backend 在后端实现
hetu_object_t hetu_object_base(losu_vm_t vm);
void hetu_object_pushbase(hetu_object_t obj);
void hetu_object_popbase();

hetu_object_t hetu_object_new(losu_vm_t vm);
void hetu_object_free(losu_vm_t vm, hetu_object_t obj);

#endif

#if 1  // style

#if 1  // typedef

typedef struct hetu_style_ARGB {
  uint8_t a, r, g, b;
} hetu_style_ARGB_t;

typedef int32_t hetu_style_enums_t;

typedef enum hetu_style_value_type {
  HETU_STYLE_VALUE_TYPE_DEFAULT,
  HETU_STYLE_VALUE_TYPE_PX,
  HETU_STYLE_VALUE_TYPE_PERCENT,
  HETU_STYLE_VALUE_TYPE_ARGB,
  HETU_STYLE_VALUE_TYPE_NUMBER,
  HETU_STYLE_VALUE_TYPE_ENUM,
  HETU_STYLE_VALUE_TYPE_STRING,
} hetu_style_value_type;

typedef struct hetu_style_value {
  uint8_t type;  // 0 is px, 1 is percent
  union {
    uint16_t px;
    uint16_t percent;
    hetu_style_ARGB_t argb;
    hetu_style_enums_t enums;
    float number;
    const char* str;
  } value;
} hetu_style_value, *hetu_style_value_t;

typedef void* hetu_style_private_t;

#endif

typedef struct hetu_style {
  // 尺寸
  hetu_style_value width;       // number px percent
  hetu_style_value height;      // number px percent
  hetu_style_value min_width;   // number px percent
  hetu_style_value min_height;  // number px percent
  hetu_style_value max_width;   // number px percent
  hetu_style_value max_height;  // number px percent
  // 位置
  hetu_style_value x;  // number px percent
  hetu_style_value y;  // number px percent
  // 内边距
  hetu_style_value padding_left;    // number px percent
  hetu_style_value padding_right;   // number px percent
  hetu_style_value padding_top;     // number px percent
  hetu_style_value padding_bottom;  // number px percent
  // 外边距
  hetu_style_value margin_left;    // number px percent
  hetu_style_value margin_right;   // number px percent
  hetu_style_value margin_top;     // number px percent
  hetu_style_value margin_bottom;  // number px percent
  // 边框
  hetu_style_value border_width;   // number px percent
  hetu_style_value border_color;   // argb
  hetu_style_value border_radius;  // number px percent
  // 颜色
  hetu_style_value background_color;  // argb
  hetu_style_value color;             // argb
  // 可见性
  hetu_style_value visibility;  // enum
  // 布局
  hetu_style_value display;  // enum
  // display visible &  none (no sub style)
  // display_flex
  hetu_style_value flex_direction;   // enum
  hetu_style_value flex_grow;        // number
  hetu_style_value align_items;      // enum
  hetu_style_value align_content;    // enum
  hetu_style_value justify_content;  // enum
  // 私有样式
  hetu_style_private_t private;
} hetu_style, *hetu_style_t;

losu_extern_t const hetu_style hetu_style_rootstyle;

#if 1  // color

typedef struct hetu_style_inlinecolor {
  const char* name;
  hetu_style_ARGB_t color;
} hetu_style_inlinecolor;

losu_extern_t const hetu_style_inlinecolor hetu_style_inlinecolors[];
losu_extern_t const size_t nhetu_style_inlinecolors;
#endif

#if 1  // display

typedef enum hetu_style_visibility_t {
  HETU_STYLE_VISIBILITY_VISIBLE,
  HETU_STYLE_VISIBILITY_HIDDEN,
} hetu_style_visibility_t;

typedef enum hetu_style_display_t {
  HETU_STYLE_DISPLAY_FREE,
  HETU_STYLE_DISPLAY_FLEX,
} hetu_style_display_t;

typedef enum hetu_style_flex_direction_t {
  HETU_STYLE_FLEX_DIRECTION_ROW,
  HETU_STYLE_FLEX_DIRECTION_COLUMN,
} hetu_style_flex_direction_t;

typedef enum hetu_style_align_items_t {
  HETU_STYLE_ALIGN_ITEMS_START,
  HETU_STYLE_ALIGN_ITEMS_END,
  HETU_STYLE_ALIGN_ITEMS_CENTER,
  HETU_STYLE_ALIGN_ITEMS_BASELINE,
  HETU_STYLE_ALIGN_ITEMS_STRETCH,
} hetu_style_align_items_t;

typedef enum hetu_style_align_content_t {
  HETU_STYLE_ALIGN_CONTENT_START,
  HETU_STYLE_ALIGN_CONTENT_END,
  HETU_STYLE_ALIGN_CONTENT_CENTER,
  HETU_STYLE_ALIGN_CONTENT_SPACE_BETWEEN,
  HETU_STYLE_ALIGN_CONTENT_SPACE_AROUND,
} hetu_style_align_content_t;

typedef enum hetu_style_justify_content_t {
  HETU_STYLE_JUSTIFY_CONTENT_START,
  HETU_STYLE_JUSTIFY_CONTENT_END,
  HETU_STYLE_JUSTIFY_CONTENT_CENTER,
  HETU_STYLE_JUSTIFY_CONTENT_SPACE_BETWEEN,
  HETU_STYLE_JUSTIFY_CONTENT_SPACE_AROUND,
} hetu_style_justify_content_t;
#endif

typedef struct hetu_style_exp {
  const char* name;
  hetu_style_enums_t value;
} hetu_style_exp, *hetu_style_exp_t;

typedef void (*hetu_style_widget_calculate)(losu_vm_t vm,
                                            losu_object_t obj,
                                            hetu_style_t style);

typedef void (*hetu_style_widget_set)(losu_vm_t vm,
                                      hetu_object_t obj,
                                      hetu_style_t style);

losu_extern_t void hetu_style_init(losu_vm_t vm,
                                   losu_object_t obj,
                                   hetu_style_widget_calculate calcu,
                                   hetu_style_widget_set set);

losu_extern_t void hetu_style_calculate(losu_vm_t vm,
                                        losu_object_t obj,
                                        hetu_style_t style);

losu_extern_t void hetu_style_eval(losu_vm_t vm,
                                   losu_object_t vobj,
                                   hetu_style_value_t value_out,
                                   hetu_style_exp_t exps);
// in backend
losu_extern_t void hetu_style_backend_set(hetu_backend_obj_t obj,
                                          hetu_style_t style);
#endif

#if 1  // event

typedef struct hetu_event_data {
  losu_vm_t vm;
  losu_object obj;
  void (*callback)(struct hetu_event_data*);
  void* backend_data;
} hetu_event_data, *hetu_event_data_t;

typedef void (*hetu_event_callback)(hetu_event_data_t);

losu_extern_t void hetu_event_init(losu_vm_t vm,
                                   losu_object_t widgetobj,
                                   hetu_object_t hobj,
                                   hetu_event_callback cb);
losu_extern_t void hetu_event_call(losu_vm_t vm,
                                   losu_object widgetobj,
                                   const char* eventname,
                                   int32_t argc,
                                   losu_object_t argv);
// in backend
losu_extern_t void hetu_event_callback_init(hetu_object_t hobj,
                                            hetu_event_data_t evdata);

#endif

#endif